package com.matrix.async.action;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.matrix.async.bean.AsyncConfigurationBean;
import com.matrix.async.core.APPComponent;
import com.matrix.async.core.AsyncProcessPlatform;
import com.matrix.async.core.Comsumer;
import com.matrix.async.core.InitAsync;
import com.matrix.async.core.Producer;
import com.matrix.async.core.WorkThread;
import com.matrix.async.service.AsyncConfigurationService;
import com.matrix.core.constance.SystemErrorCode;
import com.matrix.core.constance.SystemMessageCode;
import com.matrix.core.exception.GlobleException;
import com.matrix.core.pojo.AjaxResult;
import com.matrix.core.pojo.PaginationVO;
import com.matrix.core.tools.LogUtil;
import com.matrix.core.tools.StringUtils;
import com.matrix.core.tools.WebUtil;
import com.matrix.core.web.BaseAction;

/**
 * 异步任务管理控制器
 * 
 * @author Administrator
 *
 */
@Controller
@RequestMapping(value = "developer/asyncConfiguration")
public class AsyncConfigurationAction extends BaseAction {

	@Autowired
	AsyncConfigurationService asyncConfigurationService;

	@Autowired
	InitAsync initAsync;

	public static final String BEV = "AsyncConfiguration_BEV";

	List<APPComponent> list = new ArrayList<>();

	Map<String, Object> APPFactoryMap = new HashMap<String, Object>();

	AsyncProcessPlatform app = AsyncProcessPlatform.getInstance();

	final ReentrantLock lock = new ReentrantLock();

	/**
	 * 异步任务列表查询
	 * 
	 * @param asyncConfigurationBean
	 * @param pageVo
	 * @return
	 */
	@RequestMapping(value = "/list")
	public @ResponseBody AjaxResult list(AsyncConfigurationBean asyncConfigurationBean, PaginationVO pageVo) {
		return showList(asyncConfigurationService, asyncConfigurationBean, pageVo);
	}

	/**
	 * 异步任务删除
	 * 
	 * @param keys
	 * @return
	 * @throws ClassNotFoundException
	 */
	@RequestMapping(value = "/del")
	public @ResponseBody AjaxResult del(String keys) throws ClassNotFoundException {
		List<String> ids = StringUtils.strToCollToString(keys, ",");
		ArrayList<String> arrayList = new ArrayList<String>();
		for (String id : ids) {
			String appFactoryBean = asyncConfigurationService.findById(id).getAppFactoryBean();
			if (appFactoryBean.equals("true")) {
				arrayList.add(id);
			}
		}
		int i = asyncConfigurationService.remove(ids);
		if (i > 0) {
			for (String id : arrayList) {
				shutdown(id);
			}
			return new AjaxResult(AjaxResult.STATUS_SUCCESS, SystemMessageCode.DELETE_SUCCES, i);
		} else {
			throw new GlobleException(SystemErrorCode.DATA_DELETE_FAIL);
		}
	}

	/**
	 * 异步任务添加
	 * 
	 * @param asyncConfigurationBean
	 * @return
	 * @throws ClassNotFoundException
	 */
	@PostMapping(value = "/add")
	public @ResponseBody AjaxResult add(AsyncConfigurationBean asyncConfigurationBean) throws ClassNotFoundException {
		int count  = asyncConfigurationService.selectCountByTaskType(asyncConfigurationBean.getTaskType());
		if (count > 0) {
			return new AjaxResult(AjaxResult.STATUS_FAIL, "该异步任务已存在");
		}
		int i = asyncConfigurationService.add(asyncConfigurationBean);
		if (i > 0) {
			if ("true".equals(asyncConfigurationBean.getBeanUse())) {
				List<APPComponent> componentList = new ArrayList<>();
				initAsync.addAsyncBean(asyncConfigurationBean, componentList);
				start(componentList);
			}
			return new AjaxResult(AjaxResult.STATUS_SUCCESS, SystemMessageCode.ADD_SUCCES);
		} else {
			throw new GlobleException(SystemErrorCode.DATA_ADD_FAIL);
		}
	}

	/**
	 * 异步任务修改
	 * 
	 * @param asyncConfigurationBean
	 * @return
	 * @throws ClassNotFoundException
	 */
	@PostMapping(value = "/modify")
	public @ResponseBody AjaxResult modify(AsyncConfigurationBean asyncConfigurationBean)
			throws ClassNotFoundException {
		AsyncConfigurationBean findById = asyncConfigurationService.findById(asyncConfigurationBean.getId());
		if (!findById.getTaskType().equals(asyncConfigurationBean.getTaskType())) {
			if (asyncConfigurationService.selectCountByTaskType(asyncConfigurationBean.getTaskType()) > 0) {
				throw new GlobleException(SystemErrorCode.DATA_UPDATE_FAIL);
			}
		}

		Map<String, Object> modifyMap = new HashMap<String, Object>();
		modifyMap.put("id", asyncConfigurationBean.getId());
		modifyMap.put("handler", asyncConfigurationBean.getHandler());
		modifyMap.put("taskType", asyncConfigurationBean.getTaskType());
		modifyMap.put("beanUse", asyncConfigurationBean.getBeanUse());
		modifyMap.put("batchSize", asyncConfigurationBean.getBatchSize());
		modifyMap.put("startupDelay", asyncConfigurationBean.getStartupDelay());
		modifyMap.put("appFactoryBean", asyncConfigurationBean.getAppFactoryBean());

		int i = asyncConfigurationService.modifyByMap(modifyMap);
		if (i > 0) {
			if (findById.getAppFactoryBean().equals("true")) {
				shutdown(asyncConfigurationBean.getId());
			}
			if ("true".equals(asyncConfigurationBean.getBeanUse())) {
				List<APPComponent> componentList = new ArrayList<>();
				initAsync.addAsyncBean(asyncConfigurationBean, componentList);
				start(componentList);
			}
			return new AjaxResult(AjaxResult.STATUS_SUCCESS, SystemMessageCode.UPDATE_SUCCES);
		} else {
			throw new GlobleException(SystemErrorCode.DATA_UPDATE_FAIL);
		}
	}

	/**
	 * 异步任务启动
	 * 
	 * @param id
	 * @return
	 * @throws ClassNotFoundException
	 */
	@RequestMapping(value = "/run")
	public @ResponseBody AjaxResult run(String id) throws ClassNotFoundException {
		AsyncConfigurationBean asyncConfigurationBean = asyncConfigurationService.findById(id);
		if(null==asyncConfigurationBean) {
			return new AjaxResult(AjaxResult.STATUS_FAIL,"该异步任务不存在");
		}
		Map<String, Object> modifyMap = new HashMap<String, Object>();
		modifyMap.put("id", asyncConfigurationBean.getId());
		modifyMap.put("handler", asyncConfigurationBean.getHandler());
		modifyMap.put("taskType", asyncConfigurationBean.getTaskType());
		modifyMap.put("beanUse", asyncConfigurationBean.getBeanUse());
		modifyMap.put("batchSize", asyncConfigurationBean.getBatchSize());
		modifyMap.put("startupDelay", asyncConfigurationBean.getStartupDelay());
		if (asyncConfigurationBean.getAppFactoryBean().equals("true")) {
			modifyMap.put("appFactoryBean", "false");
		} else {
			modifyMap.put("appFactoryBean", "true");
		}
		int i = asyncConfigurationService.modifyByMap(modifyMap);
		if (i > 0) {
			if (asyncConfigurationBean.getAppFactoryBean().equals("true")) {
				asyncConfigurationBean.setAppFactoryBean("false");
				shutdown(id);
			} else {
				asyncConfigurationBean.setAppFactoryBean("true");
			}
			if ("true".equals(asyncConfigurationBean.getBeanUse())) {
				List<APPComponent> componentList = new ArrayList<>();
				initAsync.addAsyncBean(asyncConfigurationBean, componentList);
				start(componentList);
			}
			return new AjaxResult(AjaxResult.STATUS_SUCCESS, SystemMessageCode.UPDATE_SUCCES);
		} else {
			throw new GlobleException(SystemErrorCode.DATA_UPDATE_FAIL);
		}
	}

	/**
	 * 进入列表界面
	 */
	@RequestMapping(value = "/toList")
	public String toList() {
		return "developer/async/asyProducer-list";
	}

	/**
	 * 进入修改界面
	 * 
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "/toModify")
	public ModelAndView toModif(String id) {
		AsyncConfigurationBean asyncConfigurationBean = new AsyncConfigurationBean();
		ModelAndView modelAndView = new ModelAndView("developer/async/asyProducer-modify");
		if (id != null) {
			asyncConfigurationBean = asyncConfigurationService.findById(id);
			//WebUtil.getRequest().setAttribute("obj", asyncConfigurationBean);
			WebUtil.setSessionAttribute(BEV, asyncConfigurationBean);
		}
		modelAndView.addObject("obj", asyncConfigurationBean);
		return modelAndView;
	}

	/**
	 * 进入新增界面
	 * 
	 * @return
	 */
	@RequestMapping(value = "/toAdd")
	public String toAdd() {
		return "developer/async/asyProducer-add";
	}

	/**
	 * 异步任务开始
	 * @param list
	 */
	public void start(List<APPComponent> list) {
		final ReentrantLock lock = this.lock;
		lock.lock();
		try {
			for (APPComponent component : list) {
				try {
					app.bindComponent(component);
				} catch (RuntimeException e) {
					app.unBindComponent(component);
					app.bindComponent(component);
				}
				app.bundleComponent(component);
			}
			for (APPComponent component : list) {
				if (component instanceof Producer) {
					app.startDelay((WorkThread) AsyncProcessPlatform.getProducers().lockup(component.getName()));
				} else if (component instanceof Comsumer) {
					app.startDelay((WorkThread) AsyncProcessPlatform.getComsumers().lockup(component.getName()));
				}
			}

		} finally {
			lock.unlock();
		}
	}

	/**
	 * 停止异步任务
	 * @param id
	 */
	public void shutdown(String id) {
		final ReentrantLock lock = this.lock;
		lock.lock();
		try {
			APPComponent comsumer = (APPComponent) WebUtil.getBean("comsumer" + id);
			WorkThread lockup2 = (WorkThread) AsyncProcessPlatform.getComsumers().lockup(comsumer.getName());
			APPComponent producer = (APPComponent) WebUtil.getBean("producer" + id);
			WorkThread lockup3 = (WorkThread) AsyncProcessPlatform.getProducers().lockup(producer.getName());
			lockup2.shutdown();
			lockup3.shutdown();
		} catch (Exception e) {
			LogUtil.error("删除时异常", e);
		} finally {
			lock.unlock();
		}
	}

}